interface dragEventParam {
	drag: DragObj;
	x: number;
	y: number;
}

class DragObj extends egret.DisplayObject {
	_XTouch: number;

	_YTouch: number;

	_x: number;

	_y: number;

	_storeX: number;

	_storeY: number;

	_dragX: boolean;

	_dragY: boolean;

	_minX: number;

	_maxX: number;

	_minY: number;

	_maxY: number;

	_inMap: boolean;

	_localX: number;

	_localY: number;

	_nocmd: boolean;

	_dragObj: egret.DisplayObject;

	onDraged(): void {}
}

class MainDrag {
	static dragStartEvent = 'ENV_DRAGSTART';

	static dragEvent = 'ENV_DRAG';

	static dragendEvent = 'ENV_DRAGEND';

	static cmdEvent = 'ENV_DRAGCMD';

	// static dragClearEvent = 'ENV_DRAGCLEAR';

	Main: egret.DisplayObject;

	constructor(Main: egret.DisplayObject) {
		this.Main = Main;
		Main.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMoveMain, this);
		Main.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEndMain, this);
	}

	private onTouchEndMain(e: egret.TouchEvent): void {
		// console.log("onTouchEnd Main",e.stageX,e.stageY,this.m_drag)
		if (this.mDrag) {
			this.dragClear();
			e.stopPropagation();
		}
	}

	bindMoveArea(_moveArea: egret.DisplayObject, drag: egret.DisplayObject): void {
		const moveArea = _moveArea as DragObj;
		moveArea._nocmd = true;
		this.bindDragEx(moveArea, drag, false);
	}

	// 拖动moveArea的效果 === 拖动panel的效果！
	// 最后事件还是发到drag！
	bindDragEx(click: egret.DisplayObject, drag: egret.DisplayObject, inMap: boolean): void {
		const obj: DragObj = click as any;
		obj.touchEnabled = true;

		obj._dragX = true;
		obj._dragY = true;
		obj._dragObj = drag;
		obj._inMap = inMap;
		obj.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onDragBegin, this);
		// obj.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this);
		obj.addEventListener(egret.TouchEvent.TOUCH_END, this.onDragEnd, this);
		obj.addEventListener(
			egret.TouchEvent.TOUCH_RELEASE_OUTSIDE,
			this.onDragReleaseOutside,
			this,
		);
	}

	bindDrag(o: egret.DisplayObject, inMap: boolean): void {
		const obj: DragObj = o as any;
		this.bindDragEx(o, null, inMap);
	}

	releaseDrag(o: egret.DisplayObject): void {
		const obj: DragObj = o as any;
		obj._dragX = false;
		obj._dragY = false;
		obj._dragObj = null;
		obj.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onDragBegin, this);
		// obj.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this);
		obj.removeEventListener(egret.TouchEvent.TOUCH_END, this.onDragEnd, this);
		obj.removeEventListener(
			egret.TouchEvent.TOUCH_RELEASE_OUTSIDE,
			this.onDragReleaseOutside,
			this,
		);
	}

	mDrag: DragObj;

	// 要突破一定的阙值才能start！免得点击一次也有消息！
	dragStart = false;

	onDragBegin(e: egret.TouchEvent): void {
		const obj: DragObj = e.target;
		// ui.msglog("onTouchBegin",obj,obj._dragX,obj._dragY)

		if (isRightDown()) {
			return;
		}

		if (this.mDrag) {
			this.dragClear();
		}

		if (obj._dragX || obj._dragY) {
			// if (obj._inMap) {
			// 	if (game.getMapMainChar()) {
			// 		// 有主角不能拖动!
			// 		return;
			// 	}
			// 	getMapWindow().tempDisableScroll();
			// }

			this.mDrag = obj;
			this.dragStart = false;

			obj._x = obj.x;
			obj._y = obj.y;

			obj._storeX = obj.x + e.localX;
			obj._storeY = obj.y + e.localY;
			const drag = obj._dragObj as DragObj;
			if (drag) {
				drag._x = drag.x;
				drag._y = drag.y;
			}

			obj._localX = e.localX;
			obj._localY = e.localY;
			// 想办法记录鼠标移动的记录的坐标
			obj._XTouch = e.stageX;
			obj._YTouch = e.stageY;
			e.stopPropagation();

			// this.dispatchEventWith(MainWindow.dragStartEvent)
		}
	}

	private onTouchMoveMain(e: egret.TouchEvent): void {
		// this.checkHold(e)
		if (isRightDown()) {
			return;
		}

		if (!this.mDrag) {
			return;
		}
		// ui.msglog("onTouchMove Main",e.stageX,e.stageY,this.m_drag)

		const obj = this.mDrag;
		const [sx, sy] = getScaleToGlobal(obj.parent);

		if (obj._dragX) {
			obj.x = obj._storeX + (e.stageX - obj._XTouch) / sx;
			obj.x -= obj._localX;
			obj.x = miscUtils.clamp(obj.x, obj._minX, obj._maxX);
			// console.log("onTouchMove x" ,obj.x, obj.minX,obj.maxX)
		}
		if (obj._dragY) {
			obj.y = obj._storeY + (e.stageY - obj._YTouch) / sy;
			// console.log("onTouchMove y" ,obj.y)
			obj.y -= obj._localY;
			obj.y = miscUtils.clamp(obj.y, obj._minY, obj._maxY);
		}

		const dx = obj.x - obj._x;
		const dy = obj.y - obj._y;
		if (this.dragStart === false) {
			if (Math.abs(dx) >= 10 || Math.abs(dy) >= 10) {
				this.dragStart = true;
			} else {
				return;
			}
		}

		let drag = obj._dragObj as DragObj;
		if (drag != null) {
			obj.x = obj._x;
			obj.y = obj._y;
			drag.x = drag._x + dx;
			drag.y = drag._y + dy;
		} else {
			drag = obj;
		}

		// if (obj._inMap && game.MapGrid.ins().isLock()) {
		// 	[drag.x, drag.y] = game.MapGrid.ins().formatMapPos(drag.x, drag.y);
		// }

		// if (obj.onDraged)
		//	obj.onDraged()
		const param: dragEventParam = {
			drag,
			x: drag.x,
			y: drag.y,
		};
		drag.dispatchEventWith(MainDrag.dragEvent, false, param);
		e.stopPropagation();
	}

	private onDragEnd(e: egret.TouchEvent): void {
		// console.log("onTouchEnd ",e.stageX,e.stageY,this.m_drag)
		if (isRightDown()) {
			return;
		}

		if (this.mDrag) {
			this.dragClear();
			e.stopPropagation();
		}
	}

	private onDragReleaseOutside(e: egret.TouchEvent): void {
		console.log('onTouchReleaseOutside Main', e.stageX, e.stageY, this.mDrag);
		// if (this.m_drag)
		// {
		// 	this.dragClear()
		// 	e.stopPropagation()
		// }
	}

	addEditCmd(): void {
		const obj = this.mDrag;
		if (!this.dragStart) {
			return;
		}

		let { x } = obj;
		let { y } = obj;
		let sx = obj._x;
		let sy = obj._y;
		let drag = obj._dragObj as DragObj;
		if (drag != null) {
			sx = drag._x;
			sy = drag._y;
			x = drag.x;
			y = drag.y;
		} else {
			drag = obj;
		}

		if (x !== sx || y !== sy) {
			if (drag._nocmd) {
				drag.dispatchEventWith(MainDrag.cmdEvent, false, { drag, sx, sy });
				return;
			}

			drag.dispatchEventWith(MainDrag.dragendEvent, false);

			editor.Editor.ins().addUndo(
				() => {
					drag.x = sx;
					drag.y = sy;
					drag.dispatchEventWith(MainDrag.dragEvent, false, {
						drag,
						x: drag.x,
						y: drag.y,
					});
				},
				() => {
					drag.x = x;
					drag.y = y;
					drag.dispatchEventWith(MainDrag.dragEvent, false, {
						drag,
						x: drag.x,
						y: drag.y,
					});
				},
			);
		}
	}

	dragClear(): void {
		if (this.mDrag._inMap) {
			// getMapWindow().restoreScroll();
			this.addEditCmd();
		}

		const drag = this.mDrag;
		this.mDrag = null;

		if (this.dragStart && !drag._inMap) {
			drag.dispatchEventWith(MainDrag.dragendEvent);
		}
	}
	// drag end
}
